﻿using System;
using System.Linq.Expressions;

namespace Commons.Diagnostics
{
    public static class Contract
    {
        public static class Requires
        {
            public static void NotNull<T>( Expression<Func<T>> aExpression )
            {
                var lBody = ( (MemberExpression)aExpression.Body );
                System.Diagnostics.Contracts.Contract.Requires( 
                    ( (ConstantExpression)lBody.Expression ).Value != null,
                    string.Format( "{0} não pode ser nulo", lBody.Member.Name )
                );
            }

            public static void NotNullOrEmpty<T>( Expression<Func<T>> aExpression )
            {
                MemberExpression lBody = ( (MemberExpression)aExpression.Body );
                //Referência: http://blogs.msdn.com/b/csharpfaq/archive/2010/03/11/how-can-i-get-objects-and-property-values-from-expression-trees.aspx
                string lMember = ( aExpression.Compile()() ) as string;

                System.Diagnostics.Contracts.Contract.Requires(
                    !string.IsNullOrEmpty( lMember ),
                    string.Format( "{0} não pode ser nulo ou vazio", lBody.Member.Name )
                );
            }
        }

        public static class Assert
        {
            public static void Null<T>( Expression<Func<T>> aExpression )
            {
                var lBody = ( (MemberExpression)aExpression.Body );
                System.Diagnostics.Contracts.Contract.Assert(
                    ( (ConstantExpression)lBody.Expression ).Value == null,
                    string.Format( "{0} não pode ser nulo", lBody.Member.Name )
                );
            }

            public static void NotNull<T>( Expression<Func<T>> aExpression )
            {
                var lBody = ( (MemberExpression)aExpression.Body );
                System.Diagnostics.Contracts.Contract.Assert(
                    ( (ConstantExpression)lBody.Expression ).Value != null,
                    string.Format( "{0} não pode ser nulo", lBody.Member.Name )
                );
            }
        }
    }
}